package wgctl

import (
	"errors"
	"net"
	"time"
	log "ac-common-go/glog"
	"ac-julink/rpcagent"
	"ac-julink/tool/config"


	"git.apache.org/thrift.git/lib/go/thrift"
	"ac"
)

var thriftPoolManager *rpcagent.ThriftPoolManager

func dial(ip, port string, connTimeout time.Duration) (*rpcagent.IdleClient, error) {
	tSocket, err := thrift.NewTSocketTimeout(net.JoinHostPort(ip, port), connTimeout)
	if err != nil {
		log.Errorf("connect to wgsc error")
		return nil, err
	}
	if err := tSocket.Open(); err != nil {
		return nil, err
	}
	transport := thrift.NewStreamTransportFactory(tSocket, tSocket, true).GetTransport(tSocket)
	//	transport := thrift.NewTTransportFactory().GetTransport(tSocket)
	//	transport := thrift.NewTBufferedTransportFactory(1024).GetTransport(tSocket)
	protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()

	client := NewWGCTLClientFactory(transport, protocolFactory)
	return &rpcagent.IdleClient{Socket: tSocket, Client: client, CreateTime: time.Now()}, nil
}
func close(c *rpcagent.IdleClient) error {
	err := c.Socket.Close()
	return err
}
var httpProxy *rpcagent.Proxy

func InitTriftPool() {
	ip := config.GetConfigValue("WGNS", "http_ctl_ip")
	if ip == "" {
		log.Errorf("rpc_ctl_ip is not valid!!")
		return
	}
	httpPort := config.GetConfigValue("WGNS", "http_ctl_port")
	if httpPort == "" {
		log.Errorf("http_ctl_port is not valid!!")
		return
	}

	maxConnsPerHost, ok := config.GetConfigIntValue("WGNS", "http_ctl_maxconnsPerHost")
	if !ok {
		maxConnsPerHost = rpcagent.DEFAULTMAXCONNSPERHOST
	}

	respHeaderTimeout, ok := config.GetConfigIntValue("WGNS", "http_ctl_response_header_timeout")
	if !ok {
		respHeaderTimeout = rpcagent.DEFAULTRESPHEASERTIMEOUT
	}
	idleTimeout, ok := config.GetConfigIntValue("WGNS", "http_ctl_idletimeout")
	if !ok {
		idleTimeout = rpcagent.DEFAULTIDLETIME
	}
	retryNum, ok := config.GetConfigIntValue("WGNS", "http_ctl_retrynum")
	if !ok {
		retryNum = rpcagent.DEFAULTRETRYNUM
	}

	httpProxy = rpcagent.NewProxy(ip, httpPort, maxConnsPerHost, respHeaderTimeout, idleTimeout, retryNum,true)
	log.Infof("CTL http pool init success!")
}

func UploadDeviceCtlCmdResult_(wifiid string, cmdno int32, resultlist []*CmdExecResult_) (r ResponseCode, err error) {
	log.Infof("Rpc call UploadDeviceCtlCmdResult_ ==>>%s", wifiid)
	if thriftPoolManager == nil {
		return 1, errors.New("wgctl pool manager is nil")
	}
	args := make([]interface{}, 3)
	args[0] = wifiid
	args[1] = cmdno
	args[2] = resultlist
	result, err := thriftPoolManager.AskRpc("UploadDeviceCtlCmdResult_", args)
	if err != nil {
		return 1, err
	}
	b, ok := result.(ResponseCode)
	if !ok {
		return 1, errors.New("interface to ResponseCode failed")
	}
	return b, nil
}

func UploadWifiStatus(wifiid string, cmdseq int64, status string, cmdversion int32, statusversion int32) (r ResponseCode, err error) {
	log.Infof("Rpc call UploadWifiStatus ==>>%s", wifiid)
	if thriftPoolManager == nil {
		return 1, errors.New("wgctl pool manager is nil")
	}
	args := make([]interface{}, 5)
	args[0] = wifiid
	args[1] = cmdseq
	args[2] = status
	args[3] = cmdversion
	args[4] = statusversion
	result, err := thriftPoolManager.AskRpc("UploadWifiStatus", args)
	if err != nil {
		return 1, err
	}
	b, ok := result.(ResponseCode)
	if !ok {
		return 1, errors.New("interface to ResponseCode failed")
	}
	return b, nil
}
func UploadWifiCmdStatus(wifiid string, devid string, cmdseq int64, status string, cmdversion int32, statusversion int32) (r ResponseCode, err error) {
	log.Infof("Rpc call UploadWifiCmdStatus ==>>%s", wifiid)
	if thriftPoolManager == nil {
		return 1, errors.New("wgctl pool manager is nil")
	}
	args := make([]interface{}, 6)
	args[0] = wifiid
	args[1] = devid
	args[2] = cmdseq
	args[3] = status
	args[4] = cmdversion
	args[5] = statusversion
	result, err := thriftPoolManager.AskRpc("UploadWifiCmdStatus", args)
	if err != nil {
		return 1, err
	}
	b, ok := result.(ResponseCode)
	if !ok {
		return 1, errors.New("interface to ResponseCode failed")
	}
	return b, nil
}
func UploadCtlCmdResult_(wifiid string, cmdno int32, retno int32, retmsg string) (r ResponseCode, err error) {
	log.Infof("Rpc call UploadCtlCmdResult_ ==>>%s", wifiid)
	if thriftPoolManager == nil {
		return 1, errors.New("wgctl pool manager is nil")
	}
	args := make([]interface{}, 4)
	args[0] = wifiid
	args[1] = cmdno
	args[2] = retno
	args[3] = retmsg

	result, err := thriftPoolManager.AskRpc("UploadCtlCmdResult_", args)
	if err != nil {
		return 1, err
	}
	b, ok := result.(ResponseCode)
	if !ok {
		return 1, errors.New("interface to ResponseCode failed")
	}
	return b, nil
}

//xiaohong add
type ReportDeviceCmdResultReq struct {
	WifiId                  string `json:"wifiid"`
	CmdSeq                  int32 `json:"cmdseq"`
	DeviceCmdResultList     []*CmdExecResult_ `json:"devicecmdresultlist"`
    Status                  string `json:"status"`
    CmdVersion              int32 `json:"cmdversion"`
   StatusVersion            int32 `json:"statusversion"`
}
func ReportDeviceCmdResult(wifiid string, cmdno int32, resultlist []*CmdExecResult_, status string, cmdversion int32, statusversion int32)  (r *HttpCommonResp, err error){
	log.Infof("Rpc call ReportDeviceCmdresult ==>>%s", wifiid)
	reqctx := ac.NewZContext("", "", 0, 0,"", "zc-julink")

	req := ReportDeviceCmdResultReq{
		WifiId:   wifiid,
		CmdSeq:   cmdno,
		DeviceCmdResultList:resultlist,
		Status:status,
		CmdVersion:cmdversion,
		StatusVersion:statusversion,
	}
	var resp HttpCommonResp
	if err := httpProxy.DirectCall(reqctx, "device/report/cmdresult", "POST", "", &req, &resp); err != nil {
		log.Warningf("call reportDeviceCmdresult: err[%v]", err)
		return nil, err
	}
	return &resp, nil
}
//xiaohong add end

type ReportControlResetReq struct {
	WifiId       string `json:"wifiid"`
	Seq          int32  `json:"seq"`
	Err          int32    `json:"err"`
}
func ReportControlReset(_wifiid string ,_seq int32, _err int32)  (r *HttpCommonResp, err error){
	log.Infof("Http call ReportControlReset ==>>%s", _wifiid)
	reqctx := ac.NewZContext("", "", 0, 0,"", "zc-julink")
	req := ReportControlResetReq{
		WifiId:   _wifiid,
		Seq:    _seq,
		Err:   _err,
	}
	var resp HttpCommonResp
	if err := httpProxy.DirectCall(reqctx, "device/report/cmdreset", "POST", "", &req, &resp); err != nil {
		log.Warningf("call ReportDeviceCmdreset: err[%v]", err)
		return nil, err
	}
	return &resp, nil
}
func UploadWifiDeviceStatus(wifiid string, cmdseq int64, statuslist []*DeviceData, cmdversion int32, statusversion int32) (r ResponseCode, err error) {
	log.Infof("Rpc call UploadWifiDeviceStatus ==>>%s", wifiid)
	if thriftPoolManager == nil {
		return 1, errors.New("wgctl pool manager is nil")
	}
	args := make([]interface{}, 5)
	args[0] = wifiid
	args[1] = cmdseq
	args[2] = statuslist
	args[3] = cmdversion
	args[4] = statusversion
	result, err := thriftPoolManager.AskRpc("UploadWifiDeviceStatus", args)
	if err != nil {
		return 1, err
	}
	b, ok := result.(ResponseCode)
	if !ok {
		return 1, errors.New("interface to ResponseCode failed")
	}
	return b, nil
}
//xiaohong add
type ReportDeviceStatusReq struct {
	WifiId                string `json:"wifiid"`
	DeviceStatusList      []*DeviceData `json:"devicestatuslist"`
	CmdSeq                int64 `json:"cmdseq"`
	CmdVersion            int32 `json:"cmdversion"`
	StatusVersion         int32 `json:"statusversion"`
}

type HttpCommonResp struct {
	ResultCode int32  `json:"resultCode"`
}
func ReportDeviceStatus(wifiid string, cmdseq int64, statuslist []*DeviceData, cmdversion int32, statusversion int32) (r *HttpCommonResp, err error) {

	log.Infof("Http call reportDeviceStatus ==>>%s", wifiid)
	reqctx := ac.NewZContext("", "", 0, 0,"", "zc-julink")
	req := ReportDeviceStatusReq{
		WifiId:   wifiid,
		DeviceStatusList:   statuslist,
		CmdSeq:cmdseq,
		CmdVersion:cmdversion,
		StatusVersion:statusversion,
	}
	/*args := make([]interface{}, 5)
	args[0] = wifiid
	args[1] = cmdseq
	args[2] = statuslist
	args[3] = cmdversion
	args[4] = statusversion*/
	var resp HttpCommonResp
	if err := httpProxy.DirectCall(reqctx, "device/report/status", "POST", "", &req, &resp); err != nil {
		log.Warningf("call reportDeviceStatus: err[%v]", err)
		return nil, err
	}
	return &resp, nil
}
type HttpUpdateStatusResp struct {
	ResultCode int32  `json:"resultCode"`
	//Desc     string  `json:"desc"`
}
func ReportDeviceUpdateStatus(wifiid string, cmdseq int64, statuslist []*DeviceData, cmdversion int32, statusversion int32) (r *HttpUpdateStatusResp, err error) {

	log.Infof("Http call reportDeviceUpdateStatus ==>>%s", wifiid)
	reqctx := ac.NewZContext("", "", 0, 0,"", "zc-julink")
	req := ReportDeviceStatusReq{
		WifiId:   wifiid,
		DeviceStatusList:   statuslist,
		CmdSeq:cmdseq,
		CmdVersion:cmdversion,
		StatusVersion:statusversion,
	}

	var resp HttpUpdateStatusResp
	if err := httpProxy.DirectCall(reqctx, "device/report/status/903", "POST", "", &req, &resp); err != nil {
		log.Warningf("call reportDeviceStatus: err[%v]", err)
		return nil, err
	}
	return &resp, nil
}

//xiaohong add end

func UploadRefreshStatus(wifiid string, cmdseq int64, statuslist []*DeviceData) (r ResponseCode, err error) {
	log.Infof("Rpc call UploadRefreshStatus ==>>%s", wifiid)
	if thriftPoolManager == nil {
		return 1, errors.New("wgctl pool manager is nil")
	}
	args := make([]interface{}, 3)
	args[0] = wifiid
	args[1] = cmdseq
	args[2] = statuslist
	result, err := thriftPoolManager.AskRpc("UploadRefreshStatus", args)
	if err != nil {
		return 1, err
	}
	b, ok := result.(ResponseCode)
	if !ok {
		return 1, errors.New("interface to ResponseCode failed")
	}
	return b, nil
}

type UploadRefreshStatusStruct struct {
	WifiId                  string `json:"wifiid"`
	CmdSeq                  int64 `json:"cmdseq"`
	StatusList              []*DeviceData `json:"devicestatuslist"`
}

//202设备上报状态更新
func UploadRefreshStatusHttp(wifiid string, cmdseq int64, statuslist []*DeviceData) (r *HttpCommonResp, err error) {
	log.Infof("http call UploadRefreshStatus ==>>%s", wifiid)
	reqctx := ac.NewZContext("", "", 0, 0,"", "zc-julink")
	req := UploadRefreshStatusStruct{
		WifiId:wifiid,
		CmdSeq: cmdseq,
		StatusList:statuslist,
	}
	var resp HttpCommonResp
	if err := httpProxy.DirectCall(reqctx, "device/report/refreshstatus", "POST", "", &req, &resp); err != nil {
		log.Warningf("call reportDeviceCmdresult: err[%v]", err)
		return nil, err
	}
	return &resp, nil

}
